package co.edu.unal.visor.datasource;

import co.edu.unal.visor.datasource.util.BitWise;
import java.io.IOException;



public class BMPImageDecoder extends ImageDecoder {

	public BMPImageDecoder() {
		// por defecto, el formato BMP maneja LittleEndian
		isLE = true;
	}

	public void readImage(String path) throws IOException {
		FileReader.openFileInputStream(path);
		image = new Imagen();
		// lee bitmapfilehader

		// buffer = new byte[14];
		// bufferedinput.read(buffer);
		buffer = FileReader.readBytes(14);

		// extrae de buffer el offset de la imagen
		long PAOffset = BitWise.byteArrayToLongLE(new byte[] { (buffer[0x0A]),
				(buffer[0x0B]), (buffer[0x0C]), (buffer[0x0D]) });
		System.out.println("Offset de Pixelarray: " + PAOffset + " bytes");
		// lee el tama�o del dibheader

		// buffer = new byte[4];
		// bufferedinput.read(buffer);
		buffer = FileReader.readBytes(4);

		long DHSize = BitWise.byteArrayToLongLE(new byte[] { (buffer[0]),
				(buffer[1]), (buffer[2]), (buffer[3]) });
		// si el tama�o de dibheader es...
		switch ((int) DHSize) {
		// igual a 40, entonces es BITMAPINFOHEADER V5
		case 40:
			getBMIHV5image(PAOffset, path);
			break;
		default:
			System.out.println("no se soporta dibheader de tama�o " + DHSize
					+ " bytes");
			break;
		}

	}

	private void getBMIHV5image(long PAOffset, String path) throws IOException {
		// lee dibheader
		// buffer = new byte[40];
		// bufferedinput.read(buffer);
		buffer = FileReader.readBytes(40);
		/*
		 * Datos necesarios: (offset relativo al offset de dibheader) Bitspp: 2
		 * bytes offset A (H) Width: 4 bytes offset 4 (H) Height: 4 bytes offset
		 * 8 (H) (recordando que se leyeron ya 4 del tma�o de dibheader)
		 */
		int bitspp = BitWise.byteArrayToIntLE(new byte[] { (buffer[0x0A]),
				(buffer[0x0B]) });
		int Width = BitWise.byteArrayToIntLE(new byte[] { (buffer[0x00]),
				(buffer[0x01]), (buffer[0x02]), (buffer[0x03]) });
		int Height = BitWise.byteArrayToIntLE(new byte[] { (buffer[0x04]),
				(buffer[0x05]), (buffer[0x06]), (buffer[0x07]) });

		System.out.println("bitspp " + bitspp);
		System.out.println("Width " + Width);
		System.out.println("Height " + Height);

		image.setBitspp(bitspp);
		image.setWidth(Width);
		image.setHeight(Height);
		image.setLittleEndian(isLE);
		createStripArray(path);
	}

	private byte[][] createBMPStripArray(String path) throws IOException {
		/**/
		// retorno del cabezal al inicio de offsetarray
		FileReader.openFileInputStream(path);
		// buffer = new byte[54];
		// bufferedinput.read(buffer);
		buffer = FileReader.readBytes(54);

		int bytespp = image.getBitspp() / 8;
		// crea un stripArray con un solo arreglo de bytes
		byte[][] retorno = new byte[1][image.getHeight() * image.getWidth()
				* bytespp];
		System.out.println("retorno.length " + retorno[0].length);

		buffer = new byte[image.getBitspp() / 8];

		// tama�o del acolchado (bytes en cero que siguen despues de una fila)
		int paddingsize;
		int rowsize = (int) Math.floor(image.getBitspp() * image.getWidth()
				* 0.125);
		// numero de pixeles por fila
		System.out.println("rowsize " + rowsize);
		System.out.println("width " + image.getWidth());
		// calculo del padding
		paddingsize = 0;

		int anchoTemp = (int) rowsize;
		while ((anchoTemp % 4) != 0) {
			System.out.println("calibrando padding= " + paddingsize);
			anchoTemp++;
			paddingsize++;
		}

		int i = (int) (image.getHeight() - 1);
		while (i >= 0) {
			int j = 0;
			buffer = new byte[rowsize];
			// bufferedinput.read(buffer);
			FileReader.readBytes(buffer);
			while (j < image.getWidth() * bytespp) {
				retorno[0][i * image.getWidth() * bytespp + j] = buffer[j];
				j++;
			}
			i--;
			if (paddingsize != 0) {
				buffer = new byte[paddingsize];
				// bufferedinput.read(buffer);
				FileReader.readBytes(buffer);
			}
		}
		
		//verifica el striparray del objeto imagen
		if (image.getStripArray()!=null) {
			System.out.println("Imagen creada exitosamente ");
		}
		return retorno;
	}

	private void createStripArray(String path) throws IOException {
		this.image.setStripArray(createBMPStripArray(path));
		buffer = null;
		FileReader.closeFileInputStream();
	}
}
